home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 376-400 / 392 / spades / spades.c < prev    next >
C/C++ Source or Header  |  1995-03-14  |  48KB  |  1,726 lines

  1. /**********************************************************
  2. * PROGRAM: Spades                                         *
  3. * AUTHOR: Gregory M. Stelmack                             *
  4. * COMPILER: Lattice C V5.04                               *
  5. *      Copyright (C) 1988 Lattice, Inc.                   *
  6. * VESRION DATES:                                          *
  7. *      Version 1.0 -- February 5, 1990                    *
  8. *      Version 1.1 -- April 28, 1990                      *
  9. *           Images used for cards -- file "Spades.images" *
  10. *           must be in current directory to run.          *
  11. *           Title graphics added. New routine for         *
  12. *           choosing dealer.                              *
  13. * Tab stops set to 2,4,6,8,... for this listing.          *
  14. **********************************************************/
  15.  
  16. /* Include files */
  17.  
  18. #include <exec/types.h>
  19. #include <exec/memory.h>
  20. #include <intuition/intuition.h>
  21. #include <exec/libraries.h>
  22. #include <graphics/gfxmacros.h>
  23. #include <stdio.h>
  24. #include <math.h>
  25. #include <time.h>
  26. #include <string.h>
  27. #include <fcntl.h>
  28.  
  29. /* Structures needed for libraries */
  30.  
  31. struct IntuitionBase *IntuitionBase;
  32. struct GfxBase       *GfxBase;
  33. struct Library       *DiskfontBase;
  34.  
  35. /* Intuition Structures */
  36.  
  37. struct Screen       *CustScr;
  38. struct Window       *Wdw;
  39. struct Viewport     *WVP;
  40. struct IntuiMessage *Message;
  41.  
  42. /************** Program Constants **************/
  43. #define RP       Wdw->RPort      /* Raster Port for Graphics Routines */
  44. #define PENS        8            /* Number of Pens                    */
  45. #define DEPTH       3            /* Number of BitPlanes               */
  46. #define MLEFT       1            /* Left Mouse Button Pressed         */
  47. #define MRIGHT      2            /* Right Mouse Button Pressed        */
  48.  
  49. #define DIAMONDS    0            /* Suit Definitions */
  50. #define CLUBS       1
  51. #define HEARTS      2
  52. #define SPADES      3
  53.  
  54. #define WHITE  0xFFF             /* Palette Data */
  55. #define RED    0xF00
  56. #define GREEN  0x0F0
  57. #define BLUE   0x00F
  58. #define CYAN   0x0FF
  59. #define PURPLE 0xF0F
  60. #define YELLOW 0xFF0
  61. #define BLACK  0x000
  62.  
  63. /************** Color Map Data *****************/
  64. static USHORT colormap [PENS] =
  65. {
  66.     BLUE,      /* Pen  0 */
  67.     BLACK,     /* Pen  1 */
  68.     RED,       /* Pen  2 */
  69.     GREEN,     /* Pen  3 */
  70.     WHITE,     /* Pen  4 */
  71.     YELLOW,    /* Pen  5 */
  72.     PURPLE,    /* Pen  6 */
  73.     CYAN       /* Pen  7 */
  74. };
  75.  
  76. #define BLUP 0
  77. #define BLKP 1
  78. #define REDP 2
  79. #define GRNP 3
  80. #define WHTP 4
  81. #define YELP 5
  82. #define PURP 6
  83. #define CYNP 7
  84.  
  85. /************** Text Structure *****************/
  86. struct TextAttr StdFont =
  87. {
  88.     "topaz.font",
  89.     TOPAZ_EIGHTY,
  90.     FS_NORMAL,
  91.     FPF_ROMFONT,
  92. };
  93.  
  94. /*********** NewScreen Structure **********/
  95. struct NewScreen NewCustScr =
  96. {
  97.     0,0,            /* Left Edge, Top Edge       */
  98.     320,200,DEPTH,  /* Width, Height, Depth      */
  99.     WHTP,BLUP,      /* Detail Pen, Block Pen     */
  100.     NULL,           /* View Mode                 */
  101.     CUSTOMSCREEN,   /* Screen Type               */
  102.     &StdFont,       /* Pointer to Font           */
  103.     NULL,           /* Pointer to Title Text     */
  104.     NULL,           /* Pointer to Screen Gadgets */
  105.     NULL,           /* Pointer to CustomBitMap   */
  106. };
  107.  
  108. /*********** NewWindow Structure **********/
  109. struct NewWindow NewWdw =
  110. {
  111.     0,0,            /* Left Edge, Top Edge          */
  112.     320,200,        /* Width, Height                */
  113.     BLKP,WHTP,      /* Block Pen, Detail Pen        */
  114.     MOUSEBUTTONS | CLOSEWINDOW,      /* IDCMP Flags */
  115.     SMART_REFRESH | ACTIVATE | GIMMEZEROZERO | RMBTRAP | WINDOWCLOSE,
  116.     NULL,           /* Pointer to First Gadget      */
  117.     NULL,           /* Pointer to Check Mark image  */
  118.     "Spades, by Greg Stelmack",            /* Title */
  119.     NULL,           /* Pointer to Screen structure  */
  120.     NULL,           /* Pointer to custom Bit Map    */
  121.     0,0,            /* Minimum Width, Height        */
  122.     0,0,            /* Maximum Width, Height        */
  123.     CUSTOMSCREEN    /* Type of Screen it resides on */
  124. };
  125.  
  126. /************************* Image Data *************************/
  127. struct Image CardImage =
  128. {
  129.   0, 0,                        /* LeftEdge, TopEdge     */
  130.   42, 42, 3,                   /* Width, Height, Depth  */
  131.   NULL,                        /* Image Data            */
  132.   7, 0,                        /* PlanePick, PlaneOnOff */
  133.   NULL                         /* *NextImage            */
  134. };
  135.  
  136. #include "Spades.h"
  137.  
  138. /*************************** Arrays ***************************/
  139.  
  140. /***************************************
  141. * Deck: status of cards.               *
  142. *      0 = Undealt or played.          *
  143. *  1 thru 4 = Player who holds card.   *
  144. ***************************************/
  145. int Deck[52] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  146.                 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  147.  
  148. /***************************************
  149. * Hand: cards in each player's hand.   *
  150. *      0 = Played.                     *
  151. *  1 thru 52 = Card number.            *
  152. ***************************************/
  153. int Hand[4][13] = { {0,0,0,0,0,0,0,0,0,0,0,0,0},
  154.                     {0,0,0,0,0,0,0,0,0,0,0,0,0},
  155.                     {0,0,0,0,0,0,0,0,0,0,0,0,0},
  156.                     {0,0,0,0,0,0,0,0,0,0,0,0,0} };
  157.  
  158. /********************************************
  159. * Bid: number of tricks bid by each player. *
  160. ********************************************/          
  161. int Bid[4] = {0,0,0,0};
  162.  
  163. /********************************************
  164. * Mode: aggressiveness of each player.      *
  165. *   The number in this array is added to    *
  166. *   the strength of the hand to determine   *
  167. *   the number of tricks to bid. Higher     *
  168. *   number equals more tricks.              *
  169. ********************************************/
  170. int Mode[4] = {0,0,0,0};
  171.   
  172. /********************************************
  173. * SuitPoints: how many points are added to  *
  174. *   the strength of a hand depending on the *
  175. *   number of cards in each suit in the     *
  176. *   hand. The first row is for non-spades,  *
  177. *   the second for spades.                  *
  178. ********************************************/
  179. int SuitPoints[2][14] = { {6,3,1,0,0,0,-2,-4,-6,-8,-10,-12,-20,-50},
  180.                           {-4,-2,-1,0,0,+1,+2,+5,+8,+10,+12,+20,+50} };
  181.  
  182. /********************************************
  183. * HighCardLeft: the highest unplayed card   *
  184. *   in each suit.                           *
  185. ********************************************/
  186. int HighCardLeft[4] = {0,0,0,0};
  187.  
  188. /********************************************
  189. * Card: the card played in a trick by each  *
  190. *   player.                                 *
  191. ********************************************/
  192. int Card[4] = {0,0,0,0};
  193.   
  194. /********************************************
  195. * Value: the point value of each card held  *
  196. *   in a hand. Used by computer to determine*
  197. *   which card to play.                     *
  198. ********************************************/
  199. int Value[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
  200.  
  201. /********************************************
  202. * SuitNumber: the number of cards in each   *
  203. *   suit held by a player.                  *
  204. ********************************************/
  205. int SuitNumber[4] = {0,0,0,0};
  206.   
  207. /********************************************
  208. * CardX & CardY: The X and Y positions for  *
  209. *   the played card for each player.        *
  210. * MsgX & MsgY: The X and Y positions for    *
  211. *   single character messages for each      *
  212. *   player.                                 *
  213. ********************************************/
  214. int CardX[4] = {100,1,100,209};
  215. int CardY[4] = {99,60,1,60};
  216.   
  217. int MsgX[4] = {116,45,116,195};
  218. int MsgY[4] = {96,84,50,84};
  219.   
  220. /********************************************
  221. * OutOfSuit: Whether or not a player is out *
  222. *   of a suit.                              *
  223. ********************************************/
  224. BOOL OutOfSuit[4][4] = { {0,0,0,0},
  225.                          {0,0,0,0},
  226.                          {0,0,0,0},
  227.                          {0,0,0,0} };
  228.                           
  229. /******************** Other Global Variables ******************/
  230. char *String = "      "; /* Temporary String Storage */
  231.  
  232. int PlayerScore=0, CompScore=0, PlayerTricks=0, CompTricks=0;
  233. int HandLead=0, Button=0, TrickLead=0, PlayerBid=0, CompBid=0;
  234. int ShortSuit=0, LongSuit=0, HighCard=0, Winner=0;
  235. BOOL SpadePlayed=FALSE, AllDone=FALSE;
  236. char *CardData;
  237.  
  238. SHORT Mx=0, My=0;        /* Mouse Coordinates */
  239.  
  240. /******************** Function Declarations *******************/
  241. void Spades(), SetUpScreen(), DealCards(), ShowHand(), DrawCard();
  242. int CalcBid(),GetPlayerBid(), TakeTrick(), GetPlayerCard();
  243. int GetCompCard(),FindDealer();
  244. BOOL ValidCard();
  245. void itoa(), PrintBids(), PrintScore(), PrintTricks(), GetBids();
  246. void ReadMouse(), PlayHand(), InitVars(), CalcLead(), CalcFollow();
  247. void FinishRoutine(), WrapUp(), SuggestCard(), CountCards();
  248. void Title();
  249.  
  250. /********************* Program Begins Here ********************/
  251.  
  252. /**********************************************************
  253. * Function: main                                          *
  254. * Purpose: Open everything, play the game, close          *
  255. *          everything.                                    *
  256. **********************************************************/
  257. main()
  258. {
  259.   int fh;
  260.   unsigned int count=0;
  261.   unsigned int length=0;
  262.     
  263.     /* Open the Intuition and Graphics libraries. */
  264.   
  265.     IntuitionBase = (struct IntuitionBase *)
  266.          OpenLibrary("intuition.library",LIBRARY_VERSION);
  267.     if (IntuitionBase == NULL) 
  268.   {
  269.     printf("Can't open Intuition Library");
  270.     WrapUp();
  271.   }    
  272.     
  273.     GfxBase = (struct GfxBase *)
  274.          OpenLibrary("graphics.library",LIBRARY_VERSION);
  275.     if (GfxBase == NULL)
  276.   {
  277.     printf("Can't open Graphics Library");
  278.     WrapUp();
  279.   }
  280.   
  281.   /* Open the screen and window */
  282.     
  283.     if ((NewWdw.Screen = CustScr =
  284.       (struct Screen *)OpenScreen(&NewCustScr)) == NULL)
  285.   {
  286.     printf("Can't open new screen");
  287.     WrapUp();
  288.   }
  289.         
  290.     if (( Wdw = (struct Window *)OpenWindow(&NewWdw)) == NULL)
  291.   {
  292.     printf("Can't open new window");
  293.     WrapUp();
  294.   }
  295.       
  296.     /* Find the viewport and load color map */
  297.     
  298.     WVP = (struct ViewPort *)ViewPortAddress(Wdw);
  299.     LoadRGB4(WVP,&colormap,PENS);
  300.     
  301.   /* Seed random number generator with TIMER */
  302.   
  303.   srand(time(NULL));
  304.   
  305.   /* Load Graphic Images */
  306.   
  307.   length=52*126*2*3;
  308.   CardData = (char *)AllocMem(length,MEMF_CHIP);
  309.   if (!CardData)
  310.   {
  311.     printf("Could not allocate image memory!");
  312.     WrapUp();
  313.   }
  314.   fh = open("Spades.images",O_RDONLY,0);
  315.   if (fh==-1)
  316.   {
  317.     printf("Can't open images file!");
  318.     WrapUp();
  319.   }
  320.   count = read(fh,CardData,length);
  321.   if (count==-1)
  322.   {
  323.     printf("Error reading images file!");
  324.     WrapUp();
  325.   }
  326.     
  327.   /* Start Game */
  328.     
  329.   Spades();
  330.         
  331.   /* Close Everything */
  332.   
  333.   WrapUp();
  334. }
  335.  
  336. /**********************************************************
  337. * Function: WrapUp                                        *
  338. * Parameters: none                                        *
  339. * Return Values: none                                     *
  340. * Purpose: close everything and exit                      *
  341. **********************************************************/
  342. void WrapUp()
  343. {
  344.   if (CardData)      FreeMem((char*)CardData,52*126*2);
  345.     if (Wdw)           CloseWindow(Wdw);
  346.     if (CustScr)       CloseScreen(CustScr);
  347.     if (GfxBase)       CloseLibrary(GfxBase);
  348.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  349.   exit(0);
  350. }
  351.  
  352. /**********************************************************
  353. * Function: Spades                                        *
  354. * Parameters: None                                        *
  355. * Return Values: None                                     *
  356. * Purpose: Play a game of spades. Loop until someone      *
  357. *          scores 500.                                    *
  358. **********************************************************/
  359. void Spades()
  360. {
  361.   Title();
  362.  
  363.   AllDone=FALSE;
  364.   
  365.   /* Loop until player no longer wants to play. */
  366.   
  367.   while (!AllDone)
  368.   {
  369.     PlayerScore=CompScore=0;
  370.     HandLead=FindDealer();
  371.     
  372.     /* Loop until someone reaches 500 and there is no tie. */
  373.     
  374.     while (((PlayerScore<500)&&(CompScore<500))||(PlayerScore==CompScore))
  375.     {
  376.       SetUpScreen();
  377.       InitVars();
  378.       PrintScore();
  379.       DealCards();
  380.       GetBids();
  381.       PrintBids();
  382.       PlayHand();
  383.     }
  384.     
  385.     FinishRoutine();
  386.   }
  387. }
  388.  
  389. /**********************************************************
  390. * Function: Title                                         *
  391. * Parameters: none                                        *
  392. * Return Values: none                                     *
  393. * Purpose: draw title graphics.                           *
  394. **********************************************************/
  395. void Title()
  396. {
  397.   int i=0;
  398.   
  399.   SetRast(RP,BLUP);                    /* Clear screen */
  400.   SetAPen(RP,YELP);
  401.   SetBPen(RP,BLUP);
  402.   
  403.   /* Draw card backs */
  404.   
  405.   for (i=0; i<6 ; i++)
  406.   {
  407.     DrawImage(RP,&Image25,(i*50)+15,65);
  408.   }
  409.   
  410.   /* Flip S */
  411.   
  412.   Delay(5);
  413.   DrawImage(RP,&Image24,15,65);
  414.   Delay(5);
  415.   DrawImage(RP,&Image23,15,65);
  416.   Delay(5);
  417.   DrawImage(RP,&Image22,15,65);
  418.   Delay(5);
  419.   DrawImage(RP,&Image21,15,65);
  420.   Delay(5);
  421.   DrawImage(RP,&Image17,15,65);
  422.   Delay(5);
  423.   DrawImage(RP,&Image18,15,65);
  424.   Delay(5);
  425.   DrawImage(RP,&Image19,15,65);
  426.   Delay(5);
  427.   DrawImage(RP,&Image20,15,65);
  428.   
  429.   /* Flip P */
  430.   
  431.   Delay(5);
  432.   DrawImage(RP,&Image24,65,65);
  433.   Delay(5);
  434.   DrawImage(RP,&Image23,65,65);
  435.   Delay(5);
  436.   DrawImage(RP,&Image22,65,65);
  437.   Delay(5);
  438.   DrawImage(RP,&Image21,65,65);
  439.   Delay(5);
  440.   DrawImage(RP,&Image13,65,65);
  441.   Delay(5);
  442.   DrawImage(RP,&Image14,65,65);
  443.   Delay(5);
  444.   DrawImage(RP,&Image15,65,65);
  445.   Delay(5);
  446.   DrawImage(RP,&Image16,65,65);
  447.   
  448.   /* Flip A */
  449.   
  450.   Delay(5);
  451.   DrawImage(RP,&Image24,115,65);
  452.   Delay(5);
  453.   DrawImage(RP,&Image23,115,65);
  454.   Delay(5);
  455.   DrawImage(RP,&Image22,115,65);
  456.   Delay(5);
  457.   DrawImage(RP,&Image21,115,65);
  458.   Delay(5);
  459.   DrawImage(RP,&Image9,115,65);
  460.   Delay(5);
  461.   DrawImage(RP,&Image10,115,65);
  462.   Delay(5);
  463.   DrawImage(RP,&Image11,115,65);
  464.   Delay(5);
  465.   DrawImage(RP,&Image12,115,65);
  466.   
  467.   /* Flip D */
  468.   
  469.   Delay(5);
  470.   DrawImage(RP,&Image24,165,65);
  471.   Delay(5);
  472.   DrawImage(RP,&Image23,165,65);
  473.   Delay(5);
  474.   DrawImage(RP,&Image22,165,65);
  475.   Delay(5);
  476.   DrawImage(RP,&Image21,165,65);
  477.   Delay(5);
  478.   DrawImage(RP,&Image5,165,65);
  479.   Delay(5);
  480.   DrawImage(RP,&Image6,165,65);
  481.   Delay(5);
  482.   DrawImage(RP,&Image7,165,65);
  483.   Delay(5);
  484.   DrawImage(RP,&Image8,165,65);
  485.   
  486.   /* Flip E */
  487.   
  488.   Delay(5);
  489.   DrawImage(RP,&Image24,215,65);
  490.   Delay(5);
  491.   DrawImage(RP,&Image23,215,65);
  492.   Delay(5);
  493.   DrawImage(RP,&Image22,215,65);
  494.   Delay(5);
  495.   DrawImage(RP,&Image21,215,65);
  496.   Delay(5);
  497.   DrawImage(RP,&Image1,215,65);
  498.   Delay(5);
  499.   DrawImage(RP,&Image2,215,65);
  500.   Delay(5);
  501.   DrawImage(RP,&Image3,215,65);
  502.   Delay(5);
  503.   DrawImage(RP,&Image4,215,65);
  504.   
  505.   /* Flip S */
  506.   
  507.   Delay(5);
  508.   DrawImage(RP,&Image24,265,65);
  509.   Delay(5);
  510.   DrawImage(RP,&Image23,265,65);
  511.   Delay(5);
  512.   DrawImage(RP,&Image22,265,65);
  513.   Delay(5);
  514.   DrawImage(RP,&Image21,265,65);
  515.   Delay(5);
  516.   DrawImage(RP,&Image17,265,65);
  517.   Delay(5);
  518.   DrawImage(RP,&Image18,265,65);
  519.   Delay(5);
  520.   DrawImage(RP,&Image19,265,65);
  521.   Delay(5);
  522.   DrawImage(RP,&Image20,265,65);
  523.   
  524.   /* Prompt for pause */
  525.   
  526.   Move(RP,50,180);
  527.   Text(RP,"Click any mouse button...",25);
  528.   
  529.   ReadMouse();                         /* Pause for click */
  530. }
  531.  
  532. /**********************************************************
  533. * Function: FindDealer                                    *
  534. * Parameters: none                                        *
  535. * Return Values: the player determined to initially deal. *
  536. * Purpose: find out who deals first in a game.            *
  537. **********************************************************/
  538. int FindDealer()
  539. {
  540.   int player=0, card=0, i;
  541.   BOOL done=FALSE;
  542.  
  543.   SetRast(RP,BLUP);                    /* Clear Screen */  
  544.   SetAPen(RP,YELP);
  545.   SetBPen(RP,BLUP);
  546.   
  547.   for (i=0 ; i<52 ; i++) Deck[i]=0;    /* Set deck to undealt */
  548.   
  549.   Move(RP,70,70);                      /* Warn player of what's happening */
  550.   Text(RP,"Ace of Spades",13);
  551.   Move(RP,98,78);
  552.   Text(RP,"deals",5);
  553.   
  554.   while(!done)                         /* Loop until dealer found */
  555.   {
  556.     while(Deck[card=rand()%52]) ;      /* Find undealt card */
  557.     Deck[card]=1;                      /* Mark card as dealt */
  558.     DrawCard(CardX[player],CardY[player],card);
  559.                                        /* Draw card */
  560.     Delay(10);                         /* Pause */
  561.     if (card==51)                      /* Ace of Spades */
  562.     {
  563.       done=TRUE;
  564.       Move(RP,MsgX[player],MsgY[player]);
  565.       Text(RP,"*",1);
  566.     }
  567.     player=(++player)%4;               /* Increment player */
  568.   }
  569.   
  570.   Move(RP,200,150);                    /* Wait for player */
  571.   Text(RP,"Click mouse",11);
  572.   ReadMouse();
  573.   
  574.   SetRast(RP,BLUP);
  575.   return((++player)%4);                /* Must return player 2 to left of */
  576.                                        /* dealer. Program will later */
  577.                                        /* decrement player to find lead */
  578.                                        /* who should be to left of dealer */
  579. }
  580.   
  581. /**********************************************************
  582. * Function: SetUpScreen                                   *
  583. * Parameters: none                                        *
  584. * Return Values: none                                     *
  585. * Purpose: gets the screen ready for a new hand.          *
  586. **********************************************************/
  587. void SetUpScreen()
  588. {
  589.   /* Clear the Screen */
  590.   
  591.   SetRast(RP,BLUP);
  592.   
  593.   /* Draw the Score Box */
  594.   
  595.   SetAPen(RP,YELP);
  596.   SetBPen(RP,BLKP);
  597.   Move(RP,224,6);
  598.   Text(RP," YOU   CMP ",11);
  599.   Move(RP,224,14);
  600.   Text(RP,"SCORE SCORE",11);
  601.   Move(RP,224,22);
  602.   Text(RP,"           ",11);
  603.   Move(RP,224,30);
  604.   Text(RP," BID   BID ",11);
  605.   Move(RP,224,38);
  606.   Text(RP,"           ",11);
  607.   Move(RP,224,46);
  608.   Text(RP,"TRICK TRICK",11);
  609.   Move(RP,224,54);
  610.   Text(RP,"           ",11); 
  611.   SetAPen(RP,WHTP);
  612.   Move(RP,224,7);
  613.   Draw(RP,312,7);
  614.   Move(RP,267,0);
  615.   Draw(RP,267,55);
  616. }
  617.  
  618. /**********************************************************
  619. * Function: InitVars                                      *
  620. * Parameters: none                                        *
  621. * Return Values: none                                     *
  622. * Purpose: Initialize variables and arrays for a new hand.*
  623. **********************************************************/
  624. void InitVars()
  625. {
  626.   int i;
  627.   
  628.   /* Set Leader */
  629.   
  630.   HandLead=(--HandLead+4)%4;
  631.   TrickLead=HandLead;
  632.   
  633.   /* Reset HighCardLeft */
  634.   
  635.   HighCardLeft[0]=12;
  636.   HighCardLeft[1]=12;
  637.   HighCardLeft[2]=12;
  638.   HighCardLeft[3]=12;
  639.   
  640.   /* Reset OutOfSuit */
  641.   
  642.   for (i=0 ; i<4 ; i++)
  643.   {
  644.     OutOfSuit[i][DIAMONDS]=FALSE;
  645.     OutOfSuit[i][CLUBS]   =FALSE;
  646.     OutOfSuit[i][HEARTS]  =FALSE;
  647.     OutOfSuit[i][SPADES]  =FALSE;
  648.   }
  649.   
  650.   /* Determine Modes */
  651.   
  652.   for (i=0 ; i<4 ; i++)
  653.   {
  654.     Mode[i]=0;
  655.     if (i==HandLead) Mode[i]+=2;   /* Leader should bid higher */
  656.     if (i==0||i==2)                /* Human players -- check score */
  657.     {
  658.       if ((PlayerScore>400)&&(CompScore<350)) Mode[i]-=1;
  659.       if (PlayerScore<(CompScore-100)) Mode[i]+=1;
  660.       if (PlayerScore<(CompScore-200)) Mode[i]+=1;
  661.       if (PlayerScore>(CompScore+100)) Mode[i]-=1;
  662.     }
  663.     if (i==1||i==3)                /* Computer players -- check score */
  664.     {
  665.       if ((CompScore>400)&&(PlayerScore<350)) Mode[i]-=1;
  666.       if (CompScore<(PlayerScore-100)) Mode[i]+=1;
  667.       if (CompScore<(PlayerScore-200)) Mode[i]+=1;
  668.       if (CompScore>(PlayerScore+100)) Mode[i]-=1;
  669.     }
  670.   }
  671. }
  672.  
  673. /**********************************************************
  674. * Function: DealCards                                     *
  675. * Parameters: none                                        *
  676. * Return Values: none                                     *
  677. * Purpose: Shuffle & deal the deck to the players.        *
  678. **********************************************************/
  679. void DealCards()
  680. {
  681.   int i,j,player,cardnum[4];
  682.   
  683.   for (i=0 ; i<4 ; i++) cardnum[i]=0; /* Reset cards for each player */
  684.   for (i=0 ; i<52 ; i++) Deck[i]=0;   /* Set whole deck to undealt */
  685.   
  686.   /* Shuffle and Deal Deck */
  687.   
  688.   for (i=0 ; i<52 ; i++)
  689.   {
  690.     while(Deck[j=rand()%52]) ;       /* Find undealt card */
  691.     Deck[j]=((i/13)+1);              /* Store owning player */
  692.   }
  693.   
  694.   /* Transfer cards to player hands */
  695.   
  696.   for (i=0 ; i<52 ; i++)
  697.   {
  698.     player=Deck[i]-1;                     /* Get owning player */
  699.     Hand[player][cardnum[player]++]=i+1;  /* Store card, increment counter */
  700.   }
  701. }
  702.  
  703. /**********************************************************
  704. * Function: ShowHand                                      *
  705. * Parameters: none                                        *
  706. * Return Values: none                                     *
  707. * Purpose: To display the player's hand.                  *
  708. **********************************************************/
  709. void ShowHand()
  710. {
  711.   int i;
  712.   
  713.   /* Erase old hand */
  714.   
  715.   SetAPen(RP,BLUP);
  716.   SetOPen(RP,BLUP);
  717.   RectFill(RP,21,145,183,186);
  718.  
  719.   /* Draw each card, overlaying part of the previous one */
  720.  
  721.   for (i=0 ; i<13 ; i++)
  722.   {
  723.     if (Hand[0][i])  /* Only draw if card hasn't been played */
  724.       DrawCard(((i*10)+21),145,((Hand[0][i])-1));
  725.   }
  726. }
  727.  
  728. /**********************************************************
  729. * Function: GetBids                                       *
  730. * Parameters: none                                        *
  731. * Return values: none                                     *
  732. * Purpose: Get each player's bid.                         *
  733. **********************************************************/
  734. void GetBids()
  735. {
  736.   int i;
  737.   
  738.   for (i=0 ; i<4 ; i++) Bid[i]=0;   /* Reset bids for each player */
  739.   
  740.   /* Loop through each player */
  741.   
  742.   i=HandLead;
  743.   do
  744.   {
  745.     if (i)
  746.       Bid[i]=CalcBid(i);        /* Computer Player */
  747.      else 
  748.       Bid[i]=GetPlayerBid();    /* Human Player */
  749.     i=(++i)%4;
  750.   }  while (i!=HandLead);
  751.   
  752.   /* Calculate team contracts */
  753.   
  754.   PlayerBid=Bid[0]+Bid[2];
  755.   CompBid=Bid[1]+Bid[3];
  756.   
  757.   /* Pause for click */
  758.   
  759.   ReadMouse();
  760.   
  761.   /* Erase Bids */
  762.   
  763.   SetBPen(RP,BLUP);
  764.   for (i=0 ; i<4 ; i++)
  765.   {
  766.     Move(RP,MsgX[i],MsgY[i]);
  767.     Text(RP," ",1);
  768.   }
  769. }
  770.  
  771. /**********************************************************
  772. * Function: GetPlayerBid                                  *
  773. * Parameters: none                                        *
  774. * Return Values: bid -- number of tricks bid              *
  775. * Purpose: Get the human player's bid. Could use gadgets, *
  776. *          but this is easier to program.                 *
  777. **********************************************************/
  778. int GetPlayerBid()
  779. {
  780.   int bid=1,length;
  781.   BOOL havebid=FALSE;
  782.  
  783.   ShowHand();
  784.  
  785.   /* Draw input box */
  786.   
  787.   SetAPen(RP,YELP);
  788.   SetBPen(RP,BLKP);
  789.   Move(RP,258,142);
  790.   Text(RP,"BID",3);
  791.   Move(RP,250,150);
  792.   Text(RP,"  +  ",5);
  793.   Move(RP,250,158);
  794.   Text(RP,"   OK",5);
  795.   Move(RP,250,166);
  796.   Text(RP,"  -  ",5);
  797.   
  798.   /* Loop until OK is clicked */
  799.   
  800.   while(!havebid)
  801.   {
  802.     
  803.     /* Draw Current Bid */
  804.     
  805.     SetAPen(RP,GRNP);
  806.     SetBPen(RP,BLKP);
  807.     Move(RP,250,158);
  808.     Text(RP,"  ",2);
  809.     itoa(bid,String);
  810.     length=strlen(String);
  811.     Move(RP,(258-(4*length)),158);
  812.     Text(RP,String,length);
  813.     
  814.     /* Wait for Mouse input */
  815.     
  816.     ReadMouse();
  817.     if (Button==MLEFT)    /* Left Button Pressed */
  818.     {
  819.       if ((Mx>265)&&(Mx<274)&&(My>143)&&(My<152)) bid++;  /* plus sign  */
  820.       if ((Mx>273)&&(Mx<290)&&(My>151)&&(My<160)) havebid=TRUE; /* OK   */
  821.       if ((Mx>265)&&(Mx<274)&&(My>159)&&(My<168)) bid--;  /* minus sign */
  822.     }
  823.     if (Button==MRIGHT)   /* Right Button Pressed */
  824.     {
  825.       bid=CalcBid(0);     /* Suggest a Bid */
  826.     }
  827.     
  828.     /* Make sure bid is valid */
  829.     
  830.     if (bid<1)  bid=1;
  831.     if (bid>12) bid=12;
  832.   }
  833.   
  834.   /* Erase Input Box */
  835.   
  836.   SetAPen(RP,BLUP);
  837.   SetOPen(RP,BLUP);
  838.   RectFill(RP,250,135,291,168);
  839.   
  840.   /* Display the bid */
  841.   
  842.   SetAPen(RP,YELP);
  843.   SetBPen(RP,BLUP);
  844.   itoa(bid,String);
  845.   Move(RP,MsgX[0],MsgY[0]);
  846.   Text(RP,String,strlen(String));
  847.   
  848.   /* Send the bid back */
  849.   
  850.   return(bid);
  851. }
  852.  
  853. /**********************************************************
  854. * Function: CalcBid                                       *
  855. * Parameters: player -- number of player to calculate for *
  856. * Return Values: bid -- number of tricks                  *
  857. * Purpose: To calculate the number of tricks bid by a     *
  858. *          player.                                        *
  859. **********************************************************/
  860. int CalcBid(player)
  861. int player;
  862. {
  863.   int i,j,numsuit,points,suit,bid;
  864.   
  865.   points=0;
  866.   
  867.   /* Add up points for the non-spades suits */
  868.   
  869.   for (i=DIAMONDS ; i<SPADES ; i++)  /* Loop thru suits */
  870.   {
  871.     numsuit=0;
  872.     suit=i*13;
  873.     
  874.     /* Count cards for suit and add appropriate points */
  875.     
  876.     for (j=0 ; j<13 ; j++)
  877.     {
  878.       if (Deck[suit+j]==player+1) numsuit++;
  879.     }
  880.     points+=SuitPoints[0][numsuit];
  881.     
  882.     /* Add points for face cards */
  883.     
  884.     if (Deck[suit+12]==player+1) points+=4; /* Ace   */
  885.     if (Deck[suit+11]==player+1) points+=3; /* King  */
  886.     if (Deck[suit+10]==player+1) points+=2; /* Queen */
  887.   }
  888.   
  889.   /* Calculate spades */
  890.   
  891.     numsuit=0;
  892.     
  893.     /* Count Spades and add appropriate points */
  894.     
  895.     for (j=39 ; j<52 ; j++)
  896.     {
  897.       if (Deck[j]==player+1) numsuit++;
  898.     }
  899.     points+=SuitPoints[1][numsuit];
  900.  
  901.     /* Add points for Face Cards */
  902.  
  903.     if (Deck[51]==player+1) points+=4;  /* Ace   */
  904.     if (Deck[50]==player+1) points+=3;  /* King  */
  905.     if (Deck[49]==player+1) points+=2;  /* Queen */
  906.     if (Deck[48]==player+1) points+=1;  /* Jack  */
  907.   
  908.   points+=Mode[player];        /* Adjust for aggressiveness */
  909.   if (points<4) points=4;      /* Validate number of points */
  910.   bid=points/4;                /* Find Bid */
  911.   
  912.   /* Make sure total team bid not greater than 13 */
  913.   
  914.   i=(player+2)%4;              /* Find partner */
  915.   if ((bid+Bid[i])>13) bid=13-Bid[i];
  916.   
  917.   /* Display Bid */
  918.   
  919.   itoa(bid,String);
  920.   SetAPen(RP,YELP);
  921.   SetBPen(RP,BLUP);
  922.   Move(RP,MsgX[player],MsgY[player]);
  923.   Text(RP,String,strlen(String));
  924.   
  925.   /* Send bid back */
  926.   
  927.   return(bid);
  928. }
  929.  
  930. /**********************************************************
  931. * Function: PlayHand                                      *
  932. * Parameters: none                                        *
  933. * Return Values: none                                     *
  934. * Purpose: Play out a hand until all 13 tricks are taken. *
  935. **********************************************************/
  936. void PlayHand()
  937. {
  938.   int i;
  939.   
  940.   /* Initialize */
  941.   
  942.   PlayerTricks=CompTricks=0;
  943.   SpadePlayed=FALSE;
  944.   PrintTricks();
  945.   
  946.   /* Loop through all 13 tricks */
  947.   
  948.   for (i=0 ; i<13 ; i++)
  949.   {
  950.     TrickLead=TakeTrick();                /* Play a trick */
  951.     if ((TrickLead==0)||(TrickLead==2))   /* Who won? */
  952.       PlayerTricks++;
  953.      else
  954.       CompTricks++;
  955.     PrintTricks();                        /* Display new trick total */
  956.     
  957.     /* Indicate who won with an '*' */
  958.     
  959.     SetAPen(RP,YELP);
  960.     SetBPen(RP,BLUP);
  961.     Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
  962.     Text(RP,"*",1);
  963.     
  964.     /* Pause for click */
  965.     
  966.     ReadMouse();
  967.     
  968.     /* Erase winner indicator */
  969.     
  970.     Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
  971.     Text(RP," ",1);
  972.   }
  973.   
  974.   /* Calculate new score */
  975.   
  976.   if (PlayerTricks<PlayerBid)
  977.     PlayerScore-=(10*PlayerBid);
  978.   if (CompTricks<CompBid)
  979.     CompScore-=(10*CompBid);
  980.   if (PlayerTricks>=PlayerBid)
  981.     PlayerScore+=((10*PlayerBid)+(PlayerTricks-PlayerBid));
  982.   if (CompTricks>=CompBid)
  983.     CompScore+=((10*CompBid)+(CompTricks-CompBid));
  984.     
  985.   /* Pause for click */
  986.   
  987.   ReadMouse();  
  988. }
  989.  
  990. /**********************************************************
  991. * Function: TakeTrick                                     *
  992. * Parameters: none                                        *
  993. * Return Values: winner of trick                          *
  994. * Purpose: Each player plays a card, then determine trick *
  995. *          winner.                                        *
  996. **********************************************************/
  997. int TakeTrick()
  998. {
  999.   int i,j,leadsuit,suit,value;
  1000.   
  1001.   /* Clear previously played cards */
  1002.   
  1003.   SetAPen(RP,BLUP);
  1004.   SetOPen(RP,BLUP);
  1005.   for (i=0 ; i<4 ; i++) RectFill(RP,CardX[i],CardY[i],(CardX[i]+41),(CardY[i]+41));
  1006.   
  1007.   /* Get played cards */
  1008.   
  1009.   i=TrickLead;
  1010.   do
  1011.   {
  1012.     if (!i)
  1013.       Card[i]=GetPlayerCard();
  1014.      else
  1015.       Card[i]=GetCompCard(i);
  1016.     if (i==TrickLead)           /* First card played wins so far */
  1017.     {
  1018.       HighCard=Card[i];
  1019.       leadsuit=Card[i]/13;
  1020.       Winner=i;
  1021.     }
  1022.     else
  1023.     {
  1024.       suit=Card[i]/13;
  1025.       
  1026.       /* See if this card is the new winner */
  1027.       
  1028.       if (((suit==leadsuit)||(suit==SPADES))&&(Card[i]>HighCard))
  1029.       {
  1030.         HighCard=Card[i];
  1031.         Winner=i;
  1032.       }
  1033.       
  1034.       /* Was player out of the lead suit ? */
  1035.       
  1036.       if (suit!=leadsuit) OutOfSuit[i][leadsuit]=TRUE;
  1037.     }
  1038.     i=(++i)%4;
  1039.   } while (i!=TrickLead);
  1040.   
  1041.   ShowHand();
  1042.   
  1043.   /* Set highest card played in each suit */
  1044.   
  1045.   for (i=0 ; i<4 ; i++)
  1046.   {
  1047.     for (j=0 ; j<4 ; j++)    /* Need two loops to make sure we get all */
  1048.     {
  1049.       value=Card[j]%13;
  1050.       suit=Card[j]/13;
  1051.       if (value==HighCardLeft[suit]) HighCardLeft[suit]=value-1;
  1052.     }
  1053.   }
  1054.   
  1055.   /* Send back trick winner */
  1056.   
  1057.   return(Winner);
  1058. }
  1059.  
  1060. /**********************************************************
  1061. * Function: GetPlayerCard                                 *
  1062. * Parameters: none                                        *
  1063. * Return Values: card picked to play                      *
  1064. * Purpose: Allow player to pick card to play.             *
  1065. **********************************************************/
  1066. int GetPlayerCard()
  1067. {
  1068.   int i,x,card;
  1069.   
  1070.   /* Let player know that it's his/her turn */
  1071.   
  1072.   SetBPen(RP,BLUP);
  1073.   SetAPen(RP,YELP);
  1074.   Move(RP,200,150);
  1075.   Text(RP,"PLAY A CARD",11);
  1076.   
  1077.   /* Loop until we get a good card */
  1078.   
  1079.   FOREVER
  1080.   {
  1081.     ReadMouse();                         /* Wait for mouse click */ 
  1082.     if (Button==MRIGHT) SuggestCard();   /* Player wants a suggestion */
  1083.     if (Button==MLEFT)                   /* Did player pick a card ? */
  1084.     {
  1085.       for (i=12 ; i>=0 ; i--)            /* Check from right to left */
  1086.       {
  1087.         x=(i*10)+21;                     /* Set left corner for card */
  1088.         
  1089.         /* See if clicked inside this card and if card is still unplayed */
  1090.         
  1091.         if ((My<187)&&(My>144)&&(Mx<(x+42))&&(Mx>=x)&&(Hand[0][i]))
  1092.         {
  1093.           if (ValidCard(i))              /* Was this a playable card ? */
  1094.           {
  1095.             card=Hand[0][i]-1;
  1096.             Hand[0][i]=0;                /* Mark card as played */
  1097.             if ((card/13)==SPADES) SpadePlayed=TRUE; /* Spades have been broken */
  1098.             
  1099.             /* Erase suggestion '*' */
  1100.             
  1101.             SetAPen(RP,BLUP);
  1102.             SetOPen(RP,BLUP);
  1103.             RectFill(RP,21,136,170,144);
  1104.             
  1105.             DrawCard(CardX[0],CardY[0],card); /* Draw played card */
  1106.             
  1107.             /* Erase prompt message */
  1108.             
  1109.             SetBPen(RP,BLUP);
  1110.             Move(RP,200,150);
  1111.             Text(RP,"           ",11);
  1112.             
  1113.             /* Send back played card */
  1114.             
  1115.             return(card);
  1116.           }
  1117.           else
  1118.           
  1119.             /* if chosen card was not valid, need a new card */
  1120.             
  1121.             i=-1;
  1122.         }
  1123.       }
  1124.     }
  1125.   }
  1126. }
  1127.  
  1128. /**********************************************************
  1129. * Function: ValidCard                                     *
  1130. * Parameters: card -- card in player's hand to check      *
  1131. * Return Values: was card valid or not?                   *
  1132. * Purpose: To determine if the card chosen by the player  *
  1133. *   was valid or not.                                     *
  1134. **********************************************************/
  1135. BOOL ValidCard(card)
  1136. int card;
  1137. {
  1138.   int i,suit,leadsuit;
  1139.   
  1140.   SuitNumber[DIAMONDS]=0;
  1141.   SuitNumber[CLUBS]   =0;
  1142.   SuitNumber[HEARTS]  =0;
  1143.   SuitNumber[SPADES]  =0;
  1144.   
  1145.   /* Count number of cards player has in each suit */
  1146.   
  1147.   for (i=0 ; i<13 ; i++)
  1148.   {
  1149.     if (Hand[0][i]) SuitNumber[(Hand[0][i]-1)/13]++;
  1150.   }
  1151.   
  1152.   suit=(Hand[0][card]-1)/13; /* Find suit of played card */
  1153.   
  1154.   if (!TrickLead)            /* Player is leading */
  1155.   {
  1156.     /* If he didn't lead a spade, it was a good play */
  1157.     if (suit!=SPADES) return(TRUE);
  1158.     
  1159.     /* If he only has spades, he has no choice */ 
  1160.     if ((!SuitNumber[0])&&(!SuitNumber[1])&&(!SuitNumber[2])) return(TRUE);
  1161.     
  1162.     /* If spades have been played, he can lead anything */
  1163.     if (SpadePlayed) return(TRUE);
  1164.     
  1165.     /* Must have lead a spade when it was illegal to */
  1166.     return(FALSE);
  1167.   }
  1168.   
  1169.   /* Player doesn't lead */
  1170.   
  1171.   leadsuit=Card[TrickLead]/13;       /* Find suit that was lead */
  1172.   
  1173.   /* If he played the suit that was lead, he is OK */
  1174.   if (suit==leadsuit) return(TRUE);
  1175.   
  1176.   /* If he didn't have any, he's OK */
  1177.   if (!SuitNumber[leadsuit]) return(TRUE);
  1178.   
  1179.   /* Must have had some but didn't play them */
  1180.   return(FALSE);
  1181. }
  1182.  
  1183. /**********************************************************
  1184. * Function: CountCards                                    *
  1185. * Parameters: none                                        *
  1186. * Return Values: none                                     *
  1187. * Purpose: Count cards in each suit for a player.         *
  1188. *   Determine short and long suits.                       *
  1189. **********************************************************/
  1190. void CountCards(player)
  1191. int player;
  1192. {
  1193.   int i,card,suit,maximum,minimum;
  1194.   
  1195.   /* Initialization */
  1196.   
  1197.   SuitNumber[DIAMONDS]=0;
  1198.   SuitNumber[CLUBS]   =0;
  1199.   SuitNumber[HEARTS]  =0;
  1200.   SuitNumber[SPADES]  =0;
  1201.   
  1202.   /* Loop through all cards in the player's hand */
  1203.   
  1204.   for (i=0 ; i<13 ; i++)
  1205.   {
  1206.     if (Hand[player][i])        /* Make sure card hasn't been played */
  1207.     {
  1208.       card=Hand[player][i]-1;
  1209.       suit=card/13;
  1210.       Value[i]=6-(card%13);     /* Give lower cards a slight priority */
  1211.       SuitNumber[suit]++;       /* Count Number of Suit held */
  1212.     }
  1213.      else
  1214.       Value[i]=-10000;          /* Don't throw previously played cards */
  1215.   }
  1216.   
  1217.   /* Find short and long suits */
  1218.   
  1219.   minimum=14;
  1220.   maximum=0;
  1221.   ShortSuit=LongSuit=3;
  1222.   for (i=DIAMONDS ; i<SPADES ; i++)
  1223.   {
  1224.     if ((SuitNumber[i]<minimum)&&(SuitNumber[i]>0))
  1225.     {
  1226.       minimum=SuitNumber[i];
  1227.       ShortSuit=i;
  1228.     }
  1229.     if (SuitNumber[i]>maximum)
  1230.     {
  1231.       maximum=SuitNumber[i];
  1232.       LongSuit=i;
  1233.     }
  1234.   }
  1235. }
  1236.   
  1237. /**********************************************************
  1238. * Function: SuggestCard                                   *
  1239. * Parameters: none                                        *
  1240. * Return Values: none                                     *
  1241. * Purpose: Suggest a card for player to play.             *
  1242. **********************************************************/
  1243. void SuggestCard()
  1244. {
  1245.   int i,pick,maximum;
  1246.   
  1247.   CountCards(0);
  1248.  
  1249.   /* Go to appropriate point calculating routine */
  1250.   
  1251.   if (!TrickLead)
  1252.     CalcLead(0);
  1253.    else
  1254.     CalcFollow(0);
  1255.   
  1256.   /* Find best card (the one with the most points) */
  1257.   
  1258.   pick=0;
  1259.   maximum=Value[0];
  1260.   for (i=1 ; i<13 ; i++)
  1261.   {
  1262.     if (Value[i]>maximum)
  1263.     {
  1264.       maximum=Value[i];
  1265.       pick=i;
  1266.     }
  1267.   }
  1268.   
  1269.   /* Display an '*' over suggested card */
  1270.   
  1271.   SetAPen(RP,YELP);
  1272.   SetBPen(RP,BLUP);
  1273.   Move(RP,((pick*10))+22,142);
  1274.   Text(RP,"*",1);
  1275. }
  1276.  
  1277. /**********************************************************
  1278. * Function: GetCompCard                                   *
  1279. * Parameters: player -- player to play                    *
  1280. * Return Values: card played                              *
  1281. * Purpose: Determine which card a computer-controlled     *
  1282. *   player will play.                                     *
  1283. **********************************************************/
  1284. int GetCompCard(player)
  1285. int player;
  1286. {
  1287.   int i,pick,card,maximum;
  1288.   
  1289.   CountCards(player);
  1290.  
  1291.   /* Go to appropriate point calculating routine */
  1292.   
  1293.   if (player==TrickLead)
  1294.     CalcLead(player);
  1295.    else
  1296.     CalcFollow(player);
  1297.   
  1298.   /* Find best card (the one with the most points) */
  1299.   
  1300.   pick=0;
  1301.   maximum=Value[0];
  1302.   for (i=1 ; i<13 ; i++)
  1303.   {
  1304.     if (Value[i]>maximum)
  1305.     {
  1306.       maximum=Value[i];
  1307.       pick=i;
  1308.     }
  1309.   }
  1310.   
  1311.   card=Hand[player][pick]-1;
  1312.   if ((card/13)==3) SpadePlayed=TRUE;  /* Mark that spades have been broken */
  1313.   Hand[player][pick]=0;                /* Card has now been played */
  1314.   DrawCard(CardX[player],CardY[player],card);  /* Draw the played card */
  1315.   return(card);                        /* Send the played card back */
  1316. }
  1317.  
  1318. /**********************************************************
  1319. * Function: CalcLead                                      *
  1320. * Parameters: player -- whose hand to calculate           *
  1321. * Return Values: none                                     *
  1322. * Purpose: To calculate the value of each card in a hand  *
  1323. *          to determine which card should be played if    *
  1324. *          the hand is leading.                           *
  1325. **********************************************************/
  1326. void CalcLead(player)
  1327. int player;
  1328. {
  1329.   int i,card,suit,value;
  1330.   BOOL opponentsout=FALSE, partnerout=FALSE;
  1331.   
  1332.   /* Loop through all cards in hand */
  1333.   
  1334.   for (i=0 ; i<13 ; i++)
  1335.   {
  1336.     if (Hand[player][i])   /* Make sure card hasn't been played */
  1337.     {
  1338.       
  1339.       /* Find suit and face value */
  1340.       
  1341.       card=Hand[player][i]-1;
  1342.       suit=card/13;
  1343.       value=card%13;
  1344.       
  1345.       if ((OutOfSuit[(player+1)%4][suit])||(OutOfSuit[(player+3)%4][suit]))
  1346.         opponentsout=TRUE;
  1347.         
  1348.       if (OutOfSuit[(player+2)%4][suit])
  1349.         partnerout=TRUE;
  1350.       
  1351.       if (value==HighCardLeft[suit])  /* Card is highest left in a suit */
  1352.       {
  1353.          if (suit==SPADES)            /* Spades don't matter if someone is */
  1354.            Value[i]+=50;              /* out. */
  1355.           else
  1356.          {  
  1357.            if (opponentsout)          /* If opponents are out, don't waste */
  1358.              Value[i]-=50;            /* high cards. */
  1359.             else
  1360.              Value[i]+=50;
  1361.          }  
  1362.       }
  1363.       
  1364.       /* If player holds spades, get rid of short suit */
  1365.       if ((SuitNumber[SPADES])&&(suit==ShortSuit)) Value[i]+=250;
  1366.       
  1367.       /* If player doesn't hold spades, get rid of long suit */
  1368.       if ((!SuitNumber[SPADES])&&(suit==LongSuit)) Value[i]+=250;
  1369.       
  1370.       /* If spades aren't broken, they can't be lead */
  1371.       if ((suit==SPADES)&&(!SpadePlayed)) Value[i]-=5000;
  1372.       
  1373.       /* Lead suits your partner is out of */
  1374.       if ((suit!=SPADES)&&(partnerout)&&(!opponentsout)) Value[i]+=300;
  1375.     }
  1376.   }
  1377. }
  1378.  
  1379. /**********************************************************
  1380. * Function: CalcFollow                                    *
  1381. * Parameters: player -- whose hand to calculate           *
  1382. * Return Values: none                                     *
  1383. * Purpose: To calculate the value of each card in a hand  *
  1384. *          to determine which card should be played if    *
  1385. *          the hand is not leading.                       *
  1386. **********************************************************/
  1387. void CalcFollow(player)
  1388. int player;
  1389. {
  1390.   int i,card,suit,value,leadsuit;
  1391.   BOOL alreadywon;
  1392.   
  1393.   leadsuit=Card[TrickLead]/13;  /* Calculate the suit that was lead */
  1394.   
  1395.   /* See if partner has already won the trick */
  1396.   
  1397.   alreadywon=FALSE;
  1398.   /* See if win is guaranteed (player is last to play) */
  1399.   if ((Winner==((player+2)%4))&&(TrickLead==((player+1)%4)))
  1400.     alreadywon=TRUE;  
  1401.     
  1402.   /* See if win is probable (player is next to last to play) */
  1403.   if ((Winner==TrickLead)&&(TrickLead==((player+2)%4)))
  1404.   {
  1405.     value=Card[TrickLead]%13;
  1406.     if ((value==HighCardLeft[leadsuit])&&(value>9)) alreadywon=TRUE;
  1407.   }
  1408.  
  1409.   /* Loop through all cards in hand */
  1410.   
  1411.   for (i=0 ; i<13 ; i++)
  1412.   {
  1413.     if (Hand[player][i])  /* Make sure card hasn't been played */
  1414.     {
  1415.       
  1416.       /* Find suit and face value of card */
  1417.       
  1418.       card=Hand[player][i]-1;
  1419.       suit=card/13;
  1420.       value=card%13;
  1421.       
  1422.       if (suit==leadsuit)   /* Card is of lead suit */
  1423.       { 
  1424.         Value[i]+=5000;
  1425.         
  1426.         /* If it is the highest one left in that suit, throw it */
  1427.         if ((value==HighCardLeft[suit])&&(TrickLead!=((player+1)%4))&&(card>HighCard))
  1428.           Value[i]+=70;
  1429.           
  1430.         /* See if card will beat those previously played */
  1431.         if (card>HighCard)
  1432.         {
  1433.           if (!alreadywon)  /* Team hasn't won yet */  
  1434.           {
  1435.             if (TrickLead==((player+1)%4))  /* Can definitely take trick */
  1436.               Value[i]+=100;
  1437.              else                 
  1438.               Value[i]+=10;                 /* Maybe take trick */
  1439.           }    
  1440.            else
  1441.             Value[i]-=75;   /* If the team has one, hold high cards */
  1442.         }
  1443.         
  1444.         /* If team has already one the trick, throw low cards */
  1445.         if ((card<HighCard)&&alreadywon) Value[i]+=75;
  1446.       }
  1447.       
  1448.       /* If player is going to throw a spade, make sure it has a chance of
  1449.          winning */
  1450.       if ((suit==SPADES)&&(card>HighCard))
  1451.       {
  1452.         if (!alreadywon)
  1453.           Value[i]+=10;   /* If team hasn't won, throw the spade */
  1454.          else
  1455.           Value[i]-=1000; /* If team has won, hold high spades */
  1456.       }
  1457.       if ((suit==SPADES)&&(card<HighCard))
  1458.       {
  1459.         if (!alreadywon)
  1460.           Value[i]-=1000; /* If the team hasn't won, don't throw a losing spade */
  1461.          else
  1462.           Value[i]+=10;   /* If the team has one, throw a low spade */
  1463.       }
  1464.       
  1465.       /* If player is out of the lead suit, don't throw important cards
  1466.          in other suits */
  1467.       if ((suit!=leadsuit)&&(value==HighCardLeft[suit])) Value[i]-=100;
  1468.       
  1469.       /* If player is out of lead suit, let's see about trumping */
  1470.       if ((!SuitNumber[leadsuit])&&(suit==SPADES))
  1471.       {
  1472.         if (!alreadywon)
  1473.           Value[i]+=100;  /* If team hasn't won, trump */
  1474.          else
  1475.           Value[i]-=1000; /* If team has won, no need to trump */
  1476.       }
  1477.       
  1478.       /* If player is out of lead suit and out of spades, throw the long
  1479.          suit left (keep as many suits as possible in hand) */
  1480.       if ((!SuitNumber[leadsuit])&&(!SuitNumber[SPADES])&&(suit==LongSuit))
  1481.       {
  1482.         Value[i]+=100;
  1483.       }
  1484.       
  1485.       /* Give short suit a priority */
  1486.       if (suit==ShortSuit) Value[i]+=45;
  1487.     }
  1488.   }
  1489. }
  1490.  
  1491. /**********************************************************
  1492. * Function: PrintBids                                     *
  1493. * Parameters: none                                        *
  1494. * Return Values: none                                     *
  1495. * Purpose: Display the number of tricks bid by each team  *
  1496. *          in the score box.                              *
  1497. **********************************************************/
  1498. void PrintBids()
  1499. {
  1500.   int length=0;
  1501.   
  1502.   SetAPen(RP,GRNP);
  1503.   SetBPen(RP,BLKP);
  1504.   itoa(PlayerBid,String);
  1505.   length=strlen(String);
  1506.   Move(RP,(244-(4*length)),38);
  1507.   Text(RP,String,length);
  1508.   itoa(CompBid,String);
  1509.   length=strlen(String);
  1510.   Move(RP,(292-(4*length)),38);
  1511.   Text(RP,String,length);
  1512. }
  1513.  
  1514. /**********************************************************
  1515. * Function: PrintScore                                    *
  1516. * Parameters: none                                        *
  1517. * Return Values: none                                     *
  1518. * Purpose: Display each team's score in the score box.    *
  1519. **********************************************************/
  1520. void PrintScore()
  1521. {
  1522.   int length=0;
  1523.   
  1524.   SetAPen(RP,GRNP);
  1525.   SetBPen(RP,BLKP);
  1526.   itoa(PlayerScore,String);
  1527.   length=strlen(String);
  1528.   Move(RP,(244-(4*length)),22);
  1529.   Text(RP,String,length);
  1530.   itoa(CompScore,String);
  1531.   length=strlen(String);
  1532.   Move(RP,(292-(4*length)),22);
  1533.   Text(RP,String,length);
  1534. }
  1535.  
  1536. /**********************************************************
  1537. * Function: PrintTricks                                   *
  1538. * Parameters: none                                        *
  1539. * Return Values: none                                     *
  1540. * Purpose: Display the number of tricks taken by each     *
  1541. *          team in the score box.                         *
  1542. **********************************************************/
  1543. void PrintTricks()
  1544. {
  1545.   int length=0;
  1546.   
  1547.   SetAPen(RP,GRNP);
  1548.   SetBPen(RP,BLKP);
  1549.   itoa(PlayerTricks,String);
  1550.   length=strlen(String);
  1551.   Move(RP,(244-(4*length)),54);
  1552.   Text(RP,String,length);
  1553.   itoa(CompTricks,String);
  1554.   length=strlen(String);
  1555.   Move(RP,(292-(4*length)),54);
  1556.   Text(RP,String,length);
  1557. }
  1558.  
  1559. /**********************************************************
  1560. * Function: ReadMouse                                     *
  1561. * Parameters: none                                        *
  1562. * Return Values: none                                     *
  1563. * Purpose: Wait for mouse input, and update the mouse     *
  1564. *          variables accordingly.                         *
  1565. **********************************************************/
  1566. void ReadMouse()
  1567. {
  1568.   ULONG class;
  1569.   USHORT code;
  1570.   BOOL gotmouse=FALSE;
  1571.  
  1572.   /* Loop until we have a mouse message */
  1573.   
  1574.   while(!gotmouse)
  1575.   {
  1576.     
  1577.     /* Wait for Intuition Message */
  1578.     
  1579.     if ((Message=(struct IntuiMessage *) GetMsg(Wdw->UserPort)) == NULL)
  1580.     { 
  1581.       Wait(1L<<Wdw->UserPort->mp_SigBit);
  1582.       continue;
  1583.     }
  1584.     
  1585.     /* Interpret Message */
  1586.     
  1587.     class = Message->Class;
  1588.     code = Message->Code;
  1589.     Mx=((SHORT) Message->MouseX) - 4;  /* Adjustments for        */
  1590.     My=((SHORT) Message->MouseY) - 12; /* GIMMEZEROZERO Window   */
  1591.  
  1592.     /* See if Window Close Box clicked */
  1593.     
  1594.     if (class & CLOSEWINDOW) WrapUp();
  1595.     
  1596.     /* Otherwise, make sure Message was caused by mouse */
  1597.     
  1598.     if (class & MOUSEBUTTONS)
  1599.     {
  1600.       switch(code)
  1601.       {
  1602.         
  1603.         /* Left Button Released */
  1604.         
  1605.         case SELECTUP:
  1606.            Button=MLEFT;
  1607.            gotmouse=TRUE;
  1608.            break;
  1609.         
  1610.         /* Right Button Released */
  1611.         
  1612.         case MENUUP:   
  1613.            Button=MRIGHT;
  1614.            gotmouse=TRUE;
  1615.            break;
  1616.            
  1617.         /* Other Input */
  1618.         
  1619.         default:
  1620.            gotmouse=FALSE;
  1621.       }   
  1622.     }
  1623.     ReplyMsg(Message);
  1624.   }
  1625.  
  1626. /**********************************************************
  1627. * Function: DrawCard                                      *
  1628. * Parameters: x -- x coordinate of top left corner        *
  1629. *             y -- y coordinate of top left corner        *
  1630. *           card -- number of card to draw                *
  1631. * Return Values: none                                     *
  1632. * Purpose: Draw a card.                                   *
  1633. **********************************************************/   
  1634. void DrawCard(x, y, card)
  1635. int x, y, card;
  1636. {
  1637.   CardImage.ImageData = (UWORD *)(CardData+card*126*6);
  1638.   DrawImage(RP, &CardImage, x, y);
  1639. }
  1640.  
  1641. /**********************************************************
  1642. * Function: FinishRoutine                                 *
  1643. * Parameters: none                                        *
  1644. * Return Values: none                                     *
  1645. * Purpose: Display final score, ask to play again.        *
  1646. **********************************************************/
  1647. void FinishRoutine()
  1648. {
  1649.   BOOL haveinput;
  1650.   
  1651.   SetRast(RP,BLUP);
  1652.   
  1653.   SetAPen(RP,WHTP);
  1654.   SetBPen(RP,BLUP);
  1655.   
  1656.   Move(RP,112,56);
  1657.   Text(RP,"FINAL SCORE:",12);
  1658.   Move(RP,80,72);
  1659.   Text(RP,"YOU:",4);
  1660.   Move(RP,184,72);
  1661.   Text(RP,"ME:",3);
  1662.   SetAPen(RP,YELP);
  1663.   itoa(PlayerScore,String);
  1664.   Move(RP,116,72);
  1665.   Text(RP,String,strlen(String));
  1666.   itoa(CompScore,String);
  1667.   Move(RP,212,72);
  1668.   Text(RP,String,strlen(String));
  1669.   
  1670.   Move(RP,112,96);
  1671.   Text(RP,"PLAY AGAIN ?",12);
  1672.   SetAPen(RP,BLKP);
  1673.   SetBPen(RP,WHTP);
  1674.   Move(RP,112,112);
  1675.   Text(RP,"YES",3);
  1676.   Move(RP,188,112);
  1677.   Text(RP,"NO",2);
  1678.   
  1679.   haveinput=FALSE;
  1680.   while (!haveinput)
  1681.   {
  1682.     ReadMouse();
  1683.     if ((Mx>111)&&(Mx<136)&&(My>105)&&(My<114))
  1684.     {
  1685.       haveinput=TRUE;
  1686.       AllDone=FALSE;
  1687.     }
  1688.     if ((Mx>187)&&(Mx<204)&&(My>105)&&(My<114))
  1689.     {
  1690.       haveinput=TRUE;
  1691.       AllDone=TRUE;
  1692.     }
  1693.   }
  1694. }
  1695.  
  1696. /**********************************************************
  1697. * Function: itoa                                          *
  1698. * Parameters: n -- number to convert                      *
  1699. *             s -- pointer to result string               *
  1700. * Return Values: none                                     *
  1701. * Purpose: Convert an integer to a string so it can be    *
  1702. *          used by the Text function. Lattice does not    *
  1703. *          have one.                                      *
  1704. **********************************************************/
  1705. void itoa(n,s)
  1706. char *s;
  1707. int n;
  1708. {
  1709.   int i=0;
  1710.   BOOL sign=FALSE;
  1711.   
  1712.   if (n<0)
  1713.   {
  1714.     sign=TRUE;
  1715.     n=-n;
  1716.   }
  1717.   do
  1718.   {
  1719.     s[i++]=n%10+'0';
  1720.   } while((n/=10)>0);
  1721.   if (sign) s[i++]='-';
  1722.   s[i]='\0';
  1723.   strrev(s);
  1724. }
  1725.